
#ifndef __IQF_H__
#define __IQF_H__

#include <cegfx/ceexport.h>

typedef unsigned int InterfaceID;


#define IQF_INTERFACE(Name)																							\
	struct InterfaceData {																								\
		static inline const char* GetName ()	{	return #Name;	}							\
	}

#define IQF_DECLARATION																													\
	private:																																			\
		int	iqf_count;																															\
	public:																																				\
		virtual void AddRef () { ++iqf_count; }																			\
		virtual void Release () { --iqf_count; if (iqf_count <= 0) delete this; }		\
		virtual int GetRefCount () const { return iqf_count; }											\
		virtual void *QueryInterface (InterfaceID id);															\
	private:

		
#define IQF_CONSTRUCT this->iqf_count = 0;

#define IQF_IMPLEMENTATION_BEGIN(Name)																	\
	void* Name::QueryInterface(InterfaceID id)														\
	{

#define IQF_IMPLEMENTATION_INTERFACE(Interface)													\
		if (id == InterfaceInformation<Interface>::GetID())									\
		{																																		\
			return static_cast<Interface*>(this);															\
		}
		

#define IQF_IMPLEMENTATION_END()																				\
		IQF_IMPLEMENTATION_INTERFACE(iBase);																\
		return 0;																														\
	}


struct iBase
{
	IQF_INTERFACE(iBase);

	virtual void AddRef () = 0;

	virtual void Release () = 0;

	virtual void* QueryInterface (InterfaceID id) = 0;

	virtual int GetRefCount () const = 0;

};

struct CE_GFX_API IQF
{
	static InterfaceID GetInterfaceID (const char* name);
	static InterfaceID GetNewID ();

private:
	
	static InterfaceID currentID;
};
	

template<typename Interface>
struct InterfaceInformation
{
	static inline const char* GetName ()
	{
		return Interface::InterfaceData::GetName ();
	}

	static inline InterfaceID GetID ()
	{
		InterfaceID& id = GetThisID ();
		if (id == (InterfaceID)(-1))
		{
			id = IQF::GetNewID ();
		}
		return id;
	}
private:
	static inline InterfaceID& GetThisID ()
	{
		static InterfaceID id (-1);
		return id;
	}
};


template<typename Type>
Type* IQFQueryInterface (iBase* base)
{
	return static_cast<Type*>(base->QueryInterface(InterfaceInformation<Type>::GetID ()));
}


class ceSmartPtr
{
private:
	iBase*  value;
public:
	ceSmartPtr (iBase* value) : value (value) { }
	~ceSmartPtr () {  if (value) value->Release (); }

};

#endif /* ! __IQF_H__ */ 

